import React, { CSSProperties, ReactNode, useEffect, useMemo, useRef, useState } from 'react';

type Adapt = 'width' | 'height' | 'two-way' | 'scroll' | 'auto';
type Resolution = '16:9' | '21:9' | '32:9';
export interface ScaleContainerProps {
	width?: number;
	height?: number;
	targetWidth?: number;
	targetHeight?: number;
	adapt?: Adapt;
	disabled?: boolean;
	bg?: string;
	resolution: Resolution;
	children: ReactNode;
}

/**
 *
 * @description 缩放容器组件
 * @param {*}
 */
const ScaleContainer: React.FC<ScaleContainerProps> = props => {
	const { children, disabled = false, adapt = 'width' } = props;
	const wrapDomRef = useRef<HTMLDivElement>(null);

	const [scale, setScale] = useState('1');
	const [translateArr, setTranslateArr] = useState([0, 0]);

	const widthGroup = {
		'16:9': 1920,
		'21:9': 3440,
		'32:9': 7680,
	};
	const heightGroup = {
		'16:9': 1080,
		'21:9': 1440,
		'32:9': 2160,
	};

	// 获取目标宽高
	const getWidthHeight = () => {
		return {
			targetWidth: props.targetWidth || window.innerWidth,
			targetHeight: props.targetHeight || window.innerHeight,
		};
	};

	useEffect(() => {
		const dom = wrapDomRef.current;
		if (disabled || !dom) return;
		// 监听容器变化的回调 处理缩放
		const onInternalResize = () => {
			const { targetWidth, targetHeight } = getWidthHeight();
			const width = props.width || widthGroup[props.resolution];
			const height = props.height || heightGroup[props.resolution];

			const xScale = targetWidth / width;
			const yScale = targetHeight / height;

			const autoScale = Math.min(xScale, yScale);

			const top = (targetHeight - height * xScale) / 2;
			const left = (targetWidth - width * yScale) / 2;

			const scaleMap: Record<Adapt, number[]> = {
				width: [xScale],
				height: [yScale],
				'two-way': [xScale, yScale],
				scroll: [1, 1],
				auto: [autoScale],
			};

			setTranslateArr([left <= 0 ? 0 : left, top <= 0 ? 0 : top]);
			setScale(scaleMap[adapt].join(','));
		};

		onInternalResize();

		// 监听容器的缩放
		if (!disabled && dom) {
			window.addEventListener('resize', onInternalResize);
		}

		return () => {
			if (dom) {
				window.removeEventListener('resize', onInternalResize);
			}
		};
	}, [disabled, wrapDomRef.current]);

	const getBg = (val: string) => {
		const isImage = /.(png|jpg|gif|jpeg|webp)$/;
		const isBase64 = /data:image\/.*;base64,/;
		if (isImage.test(val) || isBase64.test(val)) return val;
		return `url(${props.bg})`;
	};

	const style = useMemo<CSSProperties>(() => {
		const width = props.width || widthGroup[props.resolution];
		const height = props.height || heightGroup[props.resolution];

		const defaultStyles: CSSProperties = {
			// position: 'absolute',
			background: props.bg ? getBg(props.bg) : '',
		};

		switch (adapt) {
			case 'width':
			case 'height':
			case 'two-way': {
				return {
					...defaultStyles,
					width: width + 'px',
					height: height + 'px',
					transform: `scale(${scale})`,
					transformOrigin: 'top left',
				};
			}
			case 'auto': {
				return {
					...defaultStyles,
					width: width + 'px',
					height: height + 'px',
					transform: `scale(${scale})`,
					transformOrigin: 'top left',
					left: translateArr[0],
					top: translateArr[1],
				};
			}
			default: {
				return {
					...defaultStyles,
					width: '100vw',
					height: '100vh',
				};
			}
		}
	}, [scale, translateArr]);

	return (
		<div ref={wrapDomRef} style={{ pointerEvents: 'none', zIndex: 2, position: 'relative' }}>
			<div style={style} id="scale-container">
				{children}
			</div>
		</div>
	);
};

export default ScaleContainer;